//
//  USBObserver.m
//  Do Not Disturb
//
//  Created by Chris Karr on 9/10/07.
//  Copyright 2007 __MyCompanyName__. All rights reserved.
//

#import "USBObserver.h"
#import <IOKit/usb/IOUSBLib.h>
#import <IOKit/IOCFPlugIn.h>
#import "DNDDefines.h"

@implementation USBObserver

- (void) scan
{
	mach_port_t masterPort;
    CFMutableDictionaryRef matchingDict;

    kern_return_t kr;
 
    //Create a master port for communication with the I/O Kit
    kr = IOMasterPort (MACH_PORT_NULL, &masterPort);
    if (kr || !masterPort)
    {
        NSLog (@"ERR: Couldn't create a master I/O Kit port(%08x)", kr);
        return;
    }

    //Set up matching dictionary for class IOUSBDevice and its subclasses
    matchingDict = IOServiceMatching (kIOUSBDeviceClassName);
    if (!matchingDict)
    {
        NSLog (@"Couldn't create a USB matching dictionary");
        mach_port_deallocate(mach_task_self(), masterPort);
        return;
    }
 
	io_iterator_t iter;
	IOServiceGetMatchingServices (kIOMasterPortDefault, matchingDict, &iter);
	
	io_service_t usbDevice;
    while (usbDevice = IOIteratorNext (iter))
    {
		IOCFPlugInInterface	**plugInInterface = NULL;
		SInt32 score;

		//Create an intermediate plug-in
        kr = IOCreatePlugInInterfaceForService(usbDevice, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score);

        if ((kIOReturnSuccess != kr) || !plugInInterface)
            printf("Unable to create a plug-in (%08x)\n", kr);

		IOUSBDeviceInterface182 **dev = NULL;
    
        //Now create the device interface
		HRESULT result = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID)&dev);

        if (result || !dev)
            printf("Couldn't create a device interface (%08x)\n", (int) result);

		UInt16 vendor;
		UInt16 product;
		UInt16 release;
 
        //Check these values for confirmation
        kr = (*dev)->GetDeviceVendor(dev, &vendor);
        kr = (*dev)->GetDeviceProduct(dev, &product);
        kr = (*dev)->GetDeviceReleaseNumber(dev, &release);

        kr = (*dev)->GetDeviceReleaseNumber(dev, &release);

		UInt8 stringIndex;
        
		kr = (*dev)->USBGetProductStringIndex(dev, &stringIndex);

		IOUSBConfigurationDescriptorPtr desc;

        kr = (*dev)->GetConfigurationDescriptorPtr(dev, stringIndex, &desc);

		io_name_t deviceName;
		kr = IORegistryEntryGetName (usbDevice, deviceName);
		if (KERN_SUCCESS != kr)
		{
			NSLog (@"fail 0x%8x", kr);
			deviceName[0] = '\0';
		}
		
		NSString * name = [NSString stringWithCString:deviceName encoding:NSASCIIStringEncoding];
		
		NSMutableDictionary * dict = [NSMutableDictionary dictionary];
		[dict setValue:[NSDate date] forKey:@"date"];
		[dict setValue:[NSString stringWithFormat:@"Found USB Device: %@ (0x%x 0x%x 0x%x)", name, vendor, product, release] forKey:@"name"];
		[[NSDistributedNotificationCenter defaultCenter] postNotificationName:DND_UPDATE object:@"BluetoothObserver" userInfo:dict];

        IOObjectRelease(usbDevice);
        (*plugInInterface)->Release(plugInInterface);
        (*dev)->Release(dev);
    }
 
    //Finished with master port
    mach_port_deallocate(mach_task_self(), masterPort);
    masterPort = 0;
}

- (NSString *) getName
{
	return @"USB Devices";
}

@end
